from django.contrib.auth import login
from django.db import DatabaseError
from django.shortcuts import render
from django.views import View
from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
from django.http import JsonResponse
from django_redis import get_redis_connection

from carts.utils import merge_cart_cookie_to_redis
from .models import OAuthQQUser
from oauth.utils import check_access_token, check_open_id
import json
import re
import logging

from users.models import User

logger = logging.getLogger('django')

# Create your views here.


# QQ登陆的第一个接口：获取登陆地址
class QQURLView(View):
    def get(self, request):
        # 回调页面
        next_url = request.GET.get('next')

        # 创建工具类对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI, state=next_url)

        # 获取qq登陆页面
        login_url = oauth.get_qq_url()

        # 返回登陆地址
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'login_url': login_url})


# QQ登陆的第二个\第三个接口：扫码登陆的回调处理
class QQUserView(View):
    # QQ登陆的第二个接口：扫码登陆的回调处理
    def get(self, request):

        # 获取前端发送过来的 code 参数:
        code = request.GET.get('code')

        # 判断 code 参数是否存在
        if not code:
            # 不存在
            return JsonResponse({'code': 400, 'errmsg': '缺少code参数'})

        # 创建工具对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)

        try:
            # 携带 code 向 QQ服务器 请求 access_token
            access_token = oauth.get_access_token(code)

            # 携带access_token 向 QQ服务器 请求 openid
            openid = oauth.get_open_id(access_token)
        except Exception as e:
            logger.error(e)
            # 返回结果
            return JsonResponse({'code': 400, 'errmsg': 'oauth2.0认证失败, 即获取qq信息失败'})

        try:
            oauth_qq = OAuthQQUser.objects.get(openid=openid)

        except OAuthQQUser.DoesNotExist:
            # 登陆失败，返回openid加密值
            access_token = check_open_id(openid)

            return JsonResponse({'code': 400, 'errmsg': '登录失败', 'access_token': access_token})

        else:
            # 登陆成功，返回首页
            user = oauth_qq.user
            login(request, user)

            response = JsonResponse({'code': 0, 'errmsg': 'ok'})

            response.set_cookie('username', user.username, max_age=3600 * 24 * 14)

            # 合并购物车
            response = merge_cart_cookie_to_redis(request=request, user=user, response=response)

            return response

    # QQ登陆的第三个接口：绑定已有用户
    def post(self, request):

        # 1.获取数据
        user_dict = json.loads(request.body.decode())

        # 2.提取数据
        mobile = user_dict.get('mobile')
        password = user_dict.get('password')
        sms_code = user_dict.get('sms_code')
        access_token = user_dict.get('access_token')

        # 3.验证数据完整性
        if not all([mobile, password, sms_code, access_token]):
            return JsonResponse({'code': 400, 'errmsg': '缺少参数'})

        # 4.手机号验证
        if not re.match('^1[3-9]\d{9}$', mobile):
            return JsonResponse({'code': 400, 'errmsg': '手机号格式错误'})

        # 5.密码验证
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return JsonResponse({'code': 400, 'errmsg': '密码格式错误'})

        # 6.短信验证码验证
        # 创建连接
        redis_conn = get_redis_connection('verify_code')
        # 获取验证码
        sms_code_server = redis_conn.get('sms_%s' % mobile)

        # 判断是否过期
        if not sms_code_server:
            return JsonResponse({'code': 400, 'errmsg': '验证码失效'})

        # 验证
        if not sms_code == sms_code_server.decode():
            return JsonResponse({'code': 400, 'errmsg': '验证码错误'})

        # 7.检验 access_token
        openid = check_access_token(access_token)
        if not openid:
            return JsonResponse({'code': 400, 'errmsg': '缺少openid'})

        # 8.保存注册数据
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 用户不存在，新建用户
            user = User.objects.create_user(username=mobile, password=password, mobile=mobile)
        else:
            # 存在用户，验证密码
            if not user.check_password(password):
                return JsonResponse({'code': 400, 'errmsg': '密码错误'})

        # 9.将用户绑定openid
        try:
            OAuthQQUser.objects.create(openid=openid, user=user)
        except DatabaseError:
            return JsonResponse({'code': 400, 'errmsg': '往数据库添加数据出错'})

        # 10.实现状态保持
        login(request, user)

        # 11.创建响应
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.set_cookie('username', user.username, max_age=3600*24*14)

        # 合并购物车
        response = merge_cart_cookie_to_redis(request=request, user=user, response=response)

        return response
